#include <gtest/gtest.h>
#include <iostream>
#include <string>
#include "List.hpp"
using namespace cr;

// TestCase 事件(即: 全局事件+TestSuite 事件)

class ListTest : public testing::Test
{
public:
	static void SetUpTestCase() // 全局单元测试
	{
		// 处理全局的测试数据对象
		std::cout << "全局单元测试初始化" << std::endl;
	}

	virtual void SetUp() override // 独立单元测试
	{
		// 处理每个单元测试所需的独立数据对象（成员对象）
		std::cout << "当前单元测试初始化" << std::endl;
	}

	virtual void TearDown() override
	{
		std::cout << "当前单元测试环境释放" << std::endl;
	}

	static void TearDownTestCase()
	{
		std::cout << "全局单元测试释放" << std::endl;
	}

public:
};

TEST_F(ListTest, construct)
{
    List<int> l1;
	List<int> l2(10, 5);
	std::cout<<l2<<std::endl;

	int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	List<int> l3(array, array + sizeof(array) / sizeof(array[0]));
	std::cout<<l3<<std::endl;

	List<int> l4(l3);
	std::cout<<l4<<std::endl;

	l1 = l4;
	std::cout<<l1<<std::endl;
}

TEST_F(ListTest, push_pop)
{
	List<int> l;
	l.push_back(1);
	l.push_back(2);
	l.push_back(3);
	ASSERT_EQ(l.size(),3);
	std::cout<<l<<std::endl;

	l.pop_back();
	l.pop_back();
	std::cout<<l<<std::endl;

	l.pop_back();
	ASSERT_EQ(l.size(),0);

	// 测试PushFront与PopFron
	l.push_front(4);
	l.push_front(5);
	l.push_front(6);
	ASSERT_EQ(l.size(),3);

	l.pop_front();
	l.pop_front();
	std::cout<<l<<std::endl;
	ASSERT_EQ(l.size(),1);

	l.pop_front();
	ASSERT_EQ(l.size(),0);
}

TEST_F(ListTest, insert_erase)
{
	int array[] = {1, 2, 3, 4, 5};
	List<int> l(array, array + sizeof(array) / sizeof(array[0]));
	std::cout << l << std::endl;
	ASSERT_EQ(l.size(), 5);

	auto pos = l.begin();
	l.insert(l.begin(), 0);
	std::cout << l << std::endl;
	ASSERT_EQ(l.size(), 6);

	++pos;
	l.insert(pos, 20);
	std::cout << l << std::endl;
	ASSERT_EQ(l.size(), 7);

	l.erase(l.begin());
	l.erase(pos);
	std::cout << l << std::endl;
	ASSERT_EQ(l.size(), 5);

	// pos指向的节点已经被删除，pos迭代器失效
	std::cout << *pos << std::endl;

	auto it = l.begin();
	while (it != l.end())
	{
		it = l.erase(it); // 记录返回值，原先的it已经失效
	}
	ASSERT_EQ(l.size(), 0);
}

TEST_F(ListTest, reverse_iterator)
{
	int array[] = { 1, 2, 3, 4, 5 };
	List<int> l(array, array + sizeof(array) / sizeof(array[0]));

	auto rit = l.rbegin();
	while (rit != l.rend())
	{
		std::cout << *rit << " ";
		++rit;
	}
	std::cout << std::endl;

	const List<int> cl(l);
	auto crit = cl.crbegin();
	while (crit != cl.crend())
	{
		std::cout << *crit << " ";
		++crit;
	}
	std::cout << std::endl;
}

int main(int argc, char *argv[])
{
	testing::InitGoogleTest(&argc, argv);

	return RUN_ALL_TESTS();
}